home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / os2 / pmnos11s / dirutil.c < prev    next >
C/C++ Source or Header  |  1993-07-30  |  13KB  |  599 lines

  1. /* dirutil.c - MS-DOS directory reading routines
  2.  *
  3.  * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
  4.  * Directory sorting by Mike Chepponis, K3MC
  5.  * New version using regs.h by Russell Nelson.
  6.  * Rewritten for Turbo-C 2.0 routines by Phil Karn, KA9Q 25 March 89
  7.  */
  8. #if defined(OS2)
  9. #define INCL_DOSFILEMGR
  10. #include <os2.h>
  11. #include <stdio.h>
  12. #include <direct.h>
  13. #else
  14. #include <dir.h>
  15. #include <dos.h>
  16. #endif
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <errno.h>
  20. #include "config.h"
  21. #include "global.h"
  22. #include "proc.h"
  23. #include "session.h"
  24. #include "dirutil.h"
  25. #include "commands.h"
  26.  
  27. #ifdef CALLSERVER
  28. #include <string.h>
  29. #include <alloc.h>
  30. extern char *CDROM; /* buckbook.c: defines CDROM drive letter e.g. "s:"  */
  31. #endif
  32.  
  33. struct dirsort {
  34.     struct dirsort *next;
  35.     FILEFINDBUF3 de;
  36. };
  37. #define    NULLSORT (struct dirsort *)0
  38. #if defined(OS2)
  39. static FILEFINDBUF3 sbuf;
  40. static unsigned short usSearchCount = 1;
  41. static HDIR hDir = HDIR_CREATE;
  42. #endif
  43. static void commas __ARGS((char *dest));
  44. static int fncmp __ARGS((char *a, char *b));
  45. static void format_fname_full __ARGS((FILE *file,FILEFINDBUF3 *sbuf,int full,
  46.     int n));
  47. static void free_clist __ARGS((struct dirsort *this));
  48.  
  49. #ifdef    notdef
  50. static int getdir_nosort __ARGS((char *path,int full,FILE *file));
  51. #endif
  52. static int nextname __ARGS((int command, char *name, FILEFINDBUF3 *sbuf));
  53. static void print_free_space __ARGS((FILE *file,int n));
  54. static void undosify __ARGS((char *s));
  55. static char *wildcardize __ARGS((char *path));
  56. #if defined(OS2)
  57. int findfirst(char *, FILEFINDBUF3 *, int);
  58. int findnext(FILEFINDBUF3 *);
  59. #endif
  60. #define REGFILE    (FA_HIDDEN|FA_SYSTEM|FA_DIREC)
  61.  
  62. #define    insert_ptr(list,new)    (new->next = list,list = new)
  63.  
  64. #if defined(OS2)
  65. int findfirst(char *pszName, FILEFINDBUF3 *pBuffer, int usAttrib)
  66. {
  67. ULONG rc;
  68. ULONG ulSearchCount = 1;
  69.     rc = DosFindFirst(pszName,
  70.               &hDir,
  71.               usAttrib,
  72.               pBuffer,
  73.               sizeof(FILEFINDBUF3),
  74.               &ulSearchCount,
  75.               FIL_STANDARD);
  76.     rc = (rc == 0 ? 1 : 0);
  77.     return(rc);
  78. }
  79.  
  80.  
  81.  
  82. int findnext(FILEFINDBUF3 *pBuffer)
  83. {
  84. ULONG rc;
  85. ULONG usSearchCount = 1;
  86.     rc = DosFindNext(hDir,
  87.               pBuffer,
  88.               sizeof(FILEFINDBUF3),
  89.               &usSearchCount);
  90.  
  91.     rc = (rc == 0 ? 1 : 0);
  92.     if (rc == 0)
  93.     DosFindClose(hDir);
  94.     return(rc);
  95. }
  96. #endif
  97. /* Create a directory listing in a temp file and return the resulting file
  98.  * descriptor. If full == 1, give a full listing; else return just a list
  99.  * of names.
  100.  */
  101. FILE *
  102. dir(path,full)
  103. char *path;
  104. int full;
  105. {
  106.     FILE *fp;
  107.  
  108.     if((fp = tmpfile()) != NULLFILE){
  109.         getdir(path,full,fp);
  110.         rewind(fp);
  111.     }
  112.     return fp;
  113. }
  114.  
  115. /* find the first or next file and lowercase it. */
  116. static int
  117. nextname(command, name, sbuf)
  118. int command;
  119. char *name;
  120. #if defined(OS2)
  121. FILEFINDBUF3 *sbuf;
  122. #else
  123. struct ffblk *sbuf;
  124. #endif
  125. {
  126.     int found;
  127.  
  128.     switch(command){
  129.     case 0:
  130. #if defined(OS2)
  131.         hDir = HDIR_CREATE;
  132.         found = findfirst(name,sbuf,FILE_NORMAL | FILE_DIRECTORY);
  133. #else
  134.         found = findfirst(name,sbuf,REGFILE);
  135. #endif
  136.         break;
  137.     default:
  138.         found = findnext(sbuf);
  139.     }
  140.     found = (found == 1) ? 1 : -1;
  141.     if(found == 1)
  142.         strlwr(sbuf->achName);
  143.     return found;
  144. }
  145.  
  146. /* wildcard filename lookup */
  147. int
  148. filedir(name,times,ret_str)
  149. char *name;
  150. int times;
  151. char *ret_str;
  152. {
  153.     int rval;
  154.  
  155.     switch(times){
  156.     case 0:
  157. #if defined(OS2)
  158.         hDir = HDIR_CREATE;
  159.         rval = findfirst(name,&sbuf,FILE_NORMAL);
  160. #else
  161.         rval = findfirst(name,&sbuf,REGFILE);
  162. #endif
  163.         break;
  164.     default:
  165.         rval = findnext(&sbuf);
  166.         break;
  167.     }
  168.     if(rval == 0){
  169.         ret_str[0] = '\0';
  170.     } else {
  171.         /* Copy result to output */
  172.         strcpy(ret_str, sbuf.achName);
  173.     }
  174.     return rval;
  175. }
  176. /* do a directory list to the stream
  177.  * full = 0 -> short form, 1 is long
  178. */
  179. int
  180. getdir(path,full,file)
  181. char *path;
  182. int full;
  183. FILE *file;
  184. {
  185.     FILEFINDBUF3 sbuf;
  186.     int command = 0;
  187.     int n = 0;
  188.     struct dirsort *head, *here, *new;
  189.  
  190.     path = wildcardize(path);
  191.  
  192.     head = NULLSORT;    /* No head of chain yet... */
  193.     for(;;){
  194.         if (nextname(command, path, &sbuf) == -1)
  195.             break;
  196.         command = 1;    /* Got first one already... */
  197. #if defined(OS2)
  198.         if (sbuf.achName[0] == '.')    /* drop "." and ".." */
  199.             continue;
  200. #endif
  201.         new = (struct dirsort *) mallocw(sizeof(struct dirsort));
  202.         new->de = sbuf;    /* Copy contents of directory entry struct */
  203.  
  204.         /* insert it into the list */
  205.         if (!head || fncmp(new->de.achName, head->de.achName) < 0) {
  206.             insert_ptr(head, new);
  207.         } else {
  208.             register struct dirsort *this;
  209.             for (this = head;
  210.                 this->next != NULLSORT;
  211.                 this = this->next)
  212.                 if (fncmp(new->de.achName, this->next->de.achName) < 0)
  213.                     break;
  214.             insert_ptr(this->next, new);
  215.         }
  216.     } /* infinite FOR loop */
  217.  
  218.     for (here = head; here; here = here->next)
  219.         format_fname_full(file,&here->de,full,++n);
  220.  
  221.     /* Give back all the memory we temporarily needed... */
  222.     free_clist(head);
  223.  
  224.     if(full)
  225.         print_free_space(file, n);
  226.  
  227.     return 0;
  228. }
  229.  
  230. static int
  231. fncmp(a,b)
  232. register char *a, *b;
  233. {
  234.         int i;
  235.  
  236.     for(;;){
  237.         if (*a == '.')
  238.             return -1;
  239.         if (*b == '.')
  240.             return 1;
  241.         if ((i = *a - *b++) != 0)
  242.             return i;
  243.         if (!*a++)
  244.             return -1;
  245.     }
  246. }
  247.  
  248. #if defined(ALLCMD)
  249. /* Change working directory */
  250. int
  251. docd(argc,argv,p)
  252. int argc;
  253. char *argv[];
  254. void *p;
  255. {
  256.     char *dirname;
  257.    ULONG ulDirSize = 256;
  258.    dirname = (char *)mallocw(256);
  259.     if(argc > 1){
  260. #if !defined(OS2)
  261.         if(chdir(argv[1]) == -1){
  262. #else
  263.       if (DosSetCurrentDir(argv[1]) != 0) {
  264. #endif
  265.             tprintf("Can't change directory\n");
  266.             return 1;
  267.         }
  268.     }
  269. #if !defined(OS2)
  270.     if(getcwd(dirname,256) != NULLCHAR){
  271. #else
  272.    if(!DosQCurDir(0, dirname, &ulDirSize)){
  273. #endif
  274.         undosify(dirname);
  275.         tprintf("%s\n",dirname);
  276.     }
  277.     return 0;
  278.    free(dirname);
  279. }
  280. /* List directory to console */
  281. int
  282. dodir(argc,argv,p)
  283. int argc;
  284. char *argv[];
  285. void *p;
  286. {
  287.     char *path;
  288.     FILE *fp;
  289.     char tmpname[80];
  290.     char **margv;
  291.  
  292.     /*Make sure this comes from console - WG7J*/
  293.     if(Curproc->input != Command->input)
  294.         return 0;
  295.  
  296.     if(argc >= 2)
  297.         path = argv[1];
  298.     else
  299.         path = "*.*";
  300.  
  301.     margv = (char **)callocw(2,sizeof(char *));
  302.     tmpnam(tmpname);
  303.     fp = fopen(tmpname,WRITE_TEXT);
  304.     getdir(path,1,fp);
  305.     fclose(fp);
  306.     margv[1] = strdup(tmpname);
  307.     domore(2,margv,p);
  308.     remove(tmpname);
  309.     return 0;
  310. }
  311. /* Create directory */
  312. int
  313. domkd(argc,argv,p)
  314. int argc;
  315. char *argv[];
  316. void *p;
  317. {
  318. #if !defined(OS2)
  319.     if(mkdir(argv[1]) == -1)
  320. #else
  321.    if (DosCreateDir(argv[1], 0) != 0)
  322. #endif
  323.         tprintf("Can't make %s: %s\n",argv[1],strerror(errno));
  324.     return 0;
  325. }
  326. /* Remove directory */
  327. int
  328. dormd(argc,argv,p)
  329. int argc;
  330. char *argv[];
  331. void *p;
  332. {
  333. #if !defined(OS2)
  334.     if(rmdir(argv[1]) == -1)
  335. #else
  336.    if(DosDeleteDir(argv[1]) != 0)
  337. #endif
  338.         tprintf("Can't remove %s: %s\n",argv[1],strerror(errno));
  339.     return 0;
  340. }
  341. #endif /*ALLCMD*/
  342. /*
  343.  * Return a string with commas every 3 positions.
  344.  * the original string is replace with the string with commas.
  345.  *
  346.  * The caller must be sure that there is enough room for the resultant
  347.  * string.
  348.  *
  349.  *
  350.  * k3mc 4 Dec 87
  351.  */
  352. static void
  353. commas(dest)
  354. char *dest;
  355. {
  356.     char *src, *core;    /* Place holder for malloc */
  357.     unsigned cc;        /* The comma counter */
  358.     unsigned len;
  359.  
  360.     len = strlen(dest);
  361.     /* Make a copy, so we can muck around */
  362.     core = src = strdup(dest);
  363.  
  364.     cc = (len-1)%3 + 1;    /* Tells us when to insert a comma */
  365.  
  366.     while(*src != '\0'){
  367.         *dest++ = *src++;
  368.         if( ((--cc) == 0) && *src ){
  369.             *dest++ = ','; cc = 3;
  370.         }
  371.     }
  372.     free(core);
  373.     *dest = '\0';
  374. }
  375. /* fix up the filename so that it contains the proper wildcard set */
  376. static char *
  377. wildcardize(PCHAR path)
  378. {
  379. #if defined(OS2)
  380.     FILEFINDBUF3 sbuf;
  381.     static char ourpath[255];
  382. #else
  383.     struct ffblk sbuf;
  384.     static char ourpath[[64];
  385. #endif
  386.  
  387.     if (strchr(path, '*'))
  388.         return(path);   /* already asking for wildcard */
  389.     /* Root directory is a special case */
  390.     if(path == NULLCHAR ||
  391.        *path == '\0' ||
  392.        strcmp(path,"\\") == 0 ||
  393.        strcmp(path,"/") == 0)
  394.         path = "\\*.*";
  395. #ifdef CALLSERVER
  396.     if  (CDROM != NULLCHAR &&  strcmp(path, CDROM) == 0)  {
  397.       path = (char *) mallocw(7); /* THIS causes a memory leak ! - WG7J */
  398.       sprintf(path, "%s/*.*", CDROM);
  399.     }
  400. #endif
  401.  
  402.  
  403.     /* if they gave the name of a subdirectory, append \*.* to it */
  404. #if defined(OS2)
  405.     if ((nextname(0, path, &sbuf) == 1) &&
  406.         (sbuf.attrFile & FILE_DIRECTORY)) {
  407.         DosFindClose(hDir);
  408.         /* if there isn't enough room, give up -- it's invalid anyway */
  409.         if (strlen(path) + 4 > 254) return path;
  410. #else
  411.         if (nextname(0, path, &sbuf) &&
  412.         (sbuf.ff_attrib & FA_DIREC) &&
  413.         !nextname(1, path, &sbuf)) {
  414.  
  415.         /* if there isn't enough room, give up -- it's invalid anyway */
  416.         if (strlen(path) + 4 > 63) return path;
  417. #endif
  418.         strcpy(ourpath, path);
  419.         strcat(ourpath, "\\*.*");
  420.         return ourpath;
  421.     }
  422. #if defined(OS2)
  423.     if (hDir != HDIR_CREATE)
  424.         DosFindClose(hDir);
  425. #endif
  426.     return path;
  427. }
  428.  
  429. static void
  430. format_fname_full(file, sbuf, full, n)
  431. FILE *file;
  432. #if defined(OS2)
  433. FILEFINDBUF3 *sbuf;
  434. #else
  435. struct ffblk *sbuf;
  436. #endif
  437. int full, n;
  438. {
  439.     char line_buf[50];        /* for long dirlist */
  440.     char cbuf[20];            /* for making line_buf */
  441. #if defined(OS2)
  442.     strcpy(cbuf,sbuf->achName);
  443.     if(sbuf->attrFile & FILE_DIRECTORY) strcat(cbuf, "/");
  444. #else
  445.         strcpy(cbuf,sbuf->ff_name);
  446.      if(sbuf->ff_attrib & FA_DIREC) strcat(cbuf, "/");
  447. #endif
  448.     if (full) {
  449.         /* Long form, give other info too */
  450.         sprintf(line_buf,"%-13s",cbuf);
  451. #if defined(OS2)
  452.         if(sbuf->attrFile & FILE_DIRECTORY)
  453. #else
  454.         if(sbuf->ff_attrib & FA_DIREC)
  455. #endif
  456.             strcat(line_buf,"           ");/* 11 spaces */
  457.         else {
  458.             sprintf(cbuf,"%ld",sbuf->cbFile);
  459.             commas(cbuf);
  460.             sprintf(line_buf+strlen(line_buf),"%10s ",cbuf);
  461.         }
  462.         sprintf(line_buf+strlen(line_buf),"%2d:%02d %2d/%02d/%02d%s",
  463. #if defined(OS2)
  464.           sbuf->ftimeLastWrite.hours,    /* hour */
  465.           sbuf->ftimeLastWrite.minutes,    /* minute */
  466.           sbuf->fdateLastWrite.month,    /* month */
  467.           sbuf->fdateLastWrite.day,        /* day */
  468.           sbuf->fdateLastWrite.year + 80,    /* year */
  469. #else
  470.           (sbuf->ff_ftime >> 11) & 0x1f,    /* hour */
  471.           (sbuf->ff_ftime >> 5) & 0x3f,    /* minute */
  472.           (sbuf->ff_fdate >> 5) & 0xf,    /* month */
  473.           (sbuf->ff_fdate ) & 0x1f,        /* day */
  474.           (sbuf->ff_fdate >> 9) + 80,    /* year */
  475. #endif
  476.           (n & 1) ? "   " : "\n");
  477.         fputs(line_buf,file);
  478.     } else {
  479.         fputs(cbuf,file);
  480.         fputs("\n",file);
  481.     }
  482. }
  483. /* Provide additional information only on DIR */
  484. static void
  485. print_free_space(file, n)
  486. FILE *file;
  487. int n;
  488. {
  489.     unsigned long free_bytes, total_bytes;
  490.     char s_free[11], s_total[11];
  491.     char cbuf[20];
  492. #if defined(OS2)
  493.     FSALLOCATE dtable;
  494.     unsigned long bpcl, ulLogical;
  495.     unsigned long ulDrive;
  496.     if(n & 1)
  497.         fputs("\n",file);
  498.  
  499.     /* Find disk free space */
  500.     /*getdfree(0,&dtable);*/
  501.     DosQCurDisk(&ulDrive, &ulLogical);
  502.     DosQFSInfo(ulDrive, 1, (char *)&dtable, sizeof(dtable));
  503.     bpcl = dtable.cSectorUnit * dtable.cbSector;
  504.     free_bytes  = dtable.cUnitAvail * bpcl;
  505.     total_bytes = dtable.cUnit * bpcl;
  506. #else
  507.     struct dfree dtable;
  508.     unsigned long bpcl;
  509.     char resolved[80];    /* may need as little as 67 */
  510.     union REGS regs;
  511.     struct SREGS sregs;
  512.     int drive;
  513.  
  514.     /* do an undocumented call to find wich drive this mane resolves to */
  515.     regs.x.si = FP_OFF(path);
  516.     sregs.ds = FP_SEG(path);
  517.     regs.x.di = FP_OFF(resolved);
  518.     sregs.es = FP_SEG(resolved);
  519.     regs.h.ah = 0x60;
  520.     intdosx(®s,®s,&sregs);
  521.     drive = resolved[0] - '@';
  522.  
  523.     if(n & 1)
  524.         fputs("\n",file);
  525.  
  526.     /* Find disk free space */
  527.     getdfree(drive,&dtable);
  528.  
  529.     bpcl = dtable.df_bsec * dtable.df_sclus;
  530.     free_bytes  = dtable.df_avail * bpcl;
  531.     total_bytes = dtable.df_total * bpcl;
  532. #endif
  533.     sprintf(s_free,"%ld",free_bytes);
  534.     commas(s_free);
  535.     sprintf(s_total,"%ld",total_bytes);
  536.     commas(s_total);
  537.  
  538.     if(n)
  539.         sprintf(cbuf,"%d",n);
  540.     else
  541.         strcpy(cbuf,"No");
  542.  
  543.     fprintf(file,"%s file%s. %s bytes free. Disk size %s bytes.\n",
  544.         cbuf,(n==1? "":"s"),s_free,s_total);
  545. }
  546. static void
  547. free_clist(this)
  548. struct dirsort *this;
  549. {
  550.     struct dirsort *next;
  551.  
  552.     while (this != NULLSORT) {
  553.         next = this->next;
  554.         free(this);
  555.         this = next;
  556.     }
  557. }
  558. #ifdef    notdef
  559. static int
  560. getdir_nosort(path,full,file)
  561. char *path;
  562. int full;
  563. FILE *file;
  564. {
  565.     FILEFINDBUF3 sbuf;
  566.     int command;
  567.     int n = 0;    /* Number of directory entries */
  568.  
  569.     path = wildcardize(path);
  570.     command = 0;
  571.     while(nextname(command, path, &sbuf)){
  572.         command = 1;    /* Got first one already... */
  573. #if defined(OS2)
  574.         if (sbuf.achName[0] == '.')    /* drop "." and ".." */
  575. #else
  576.         if (sbuf.ff_name[0] == '.')    /* drop "." and ".." */
  577. #endif
  578.             continue;
  579.         format_fname_full(file, &sbuf, full, ++n);
  580.     }
  581.     if(full)
  582.         print_free_space(file, n);
  583.     return 0;
  584. }
  585. #endif
  586.  
  587. /* Translate those %$#@!! backslashes to proper form */
  588. static void
  589. undosify(s)
  590. char *s;
  591. {
  592.     while(*s != '\0'){
  593.         if(*s == '\\')
  594.             *s = '/';
  595.         s++;
  596.     }
  597. }
  598.  
  599.